#pragma once
#include "InetAddr.hpp"
#include "Socket.hpp"
#include <iostream>
#include <string>
#include <memory>
#include <functional>
#include <jsoncpp/json/json.h>

using namespace SocketModule;
// 请求
class Request
{
public:
    // 服务器接收使用
    Request()
    {
    }
    // 客户端发送使用
    Request(int x, int y, int oper) : _x(x), _y(y), _oper(oper)
    {
    }
    // 序列化
    std::string Serialize()
    {
        Json::Value root; // 创建一个空对象

        root["x"] = _x;
        root["y"] = _y;
        // root["_oper"] = _oper;
        root["oper"] = _oper;
        Json::FastWriter writer;
        std::string s = writer.write(root); // 将文件中的内容转化成字符串
        // std::cout << s << std::endl;
        return s;
    }
    // 反序列化
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root); // 把字符串写入json文件
        if (ok)
        {
            _x = root["x"].asInt();
            _y = root["y"].asInt();
            _oper = root["oper"].asInt();
        }
        return ok;
    }
    ~Request()
    {
    }
    int X() { return _x; }
    int Y() { return _y; }
    char OPER() { return _oper; }

private:
    int _x;
    int _y;
    char _oper;
};

// 应答
class Response
{
public:
    Response()
    {
    }
    Response(int result, int code) : _result(result), _code(code)
    {
    }

    std::string Serialize()
    {
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;

        Json::FastWriter writer;
        std::string s = writer.write(root);
        return s;
    }
    bool Deserialize(std::string &in)
    {
        Json::Value root;
        Json::Reader reader;
        bool ok = reader.parse(in, root);
        if (ok)
        {
            _result = root["result"].asInt();
            //_code = root["_code"].asInt();
            _code = root["code"].asInt();
        }
        return ok;
    }
    void SetResult(int result)
    {
        _result = result;
    }
    void SetCode(int code)
    {
        _code = code;
    }
    void LestRelust()
    {
        // std::cout << "result: " << _result << "code: " << _code << std::endl;
        if (_code == 0)
        {
            std::cout << _result << std::endl;
        }
        else
        {
            std::cout << "计算异常" << std::endl;
        }
    }

private:
    int _result;
    int _code;
};

using func_t = std::function<Response(Request &req)>;
const std::string sep = "\r\n";
class Protocol
{
public:
    Protocol() {}
    Protocol(func_t func) : _func(func) {}
    // 封装协议报头(应用层)
    std::string Encode(std::string &message)
    {
        std::string messagelen = std::to_string(message.size());
        // return message + sep + message + sep;
        return messagelen + sep + message + sep;
    }

    // 检测报头完整性,若完整取出完整的报文
    bool Decode(std::string &buffer, std::string *package)
    {
        ssize_t pos = buffer.find(sep);
        if (pos == std::string::npos)
        {
            return false;
        }
        std::string package_len_str = buffer.substr(0, pos);

        int package_len_int = std::stoi(package_len_str);
        // auto package_len_int = std::stoi(package_len_str);
        // int package_len_int = 54;

        // int package_len_int = 54;

        int package_len = package_len_int + package_len_str.size() + 2 * sep.size();
        if (buffer.size() < package_len)
        {
            return false;
        }
        // 一定至少有一个完整的报文

        *package = buffer.substr(pos + sep.size(), package_len_int);
        buffer.erase(0, package_len);
        return true;
    }

    void GetRequest(std::shared_ptr<Socket> sock, Inet_Addr &client)
    {
        std::string buffer;
        while (true)
        {

            int n = sock->Recv(&buffer);

            if (n > 0)
            {
                std::cout << "---------server_recv_string_buffer------" << std::endl;
                std::cout << buffer << std::endl;
                std::cout << "----------------------------------------" << std::endl;
                std::string package;
                // if (!Decode(buffer, &package))
                // {
                //     // 不足一个完整的报文继续读取
                //     continue;
                // }

                while (Decode(buffer, &package))
                {
                    LOG(LogLevel::DEBUG) << client.StringAddr() << package.c_str();
                    std::cout << "---------server_recv_string_pack-------" << std::endl;
                    std::cout << package << std::endl;
                    std::cout << "----------------------------------------" << std::endl;

                    std::cout << "---------server_recv_string_buffer------" << std::endl;
                    std::cout << buffer << std::endl;
                    std::cout << "----------------------------------------" << std::endl;
                    // 拿出的一定是一个完整的报文
                    Request req;
                    req.Deserialize(package);
                    // std::cout << req.X() << req.Y() << req.OPER() << std::endl;

                    // 运算结果
                    Response res = _func(req);

                    // 返回给客户端

                    // 序列化
                    std::string resstr = res.Serialize();
                    // 添加应用层协议报头
                    std::string sendstr = Encode(resstr);

                    std::cout << "---------server_send_string_buffer------" << std::endl;
                    std::cout << sendstr << std::endl;
                    std::cout << "----------------------------------------" << std::endl;
                    // 发送报文
                    sock->Send(sendstr);
                }
            }
            else if (n == 0)
            {
                LOG(LogLevel::INFO) << "client: " << client.StringAddr() << " Quict";
                break;
            }
            else
            {
                LOG(LogLevel::WARNING) << "client: " << client.StringAddr() << " ,recv error";
                break;
            }
        }
        sock->Close();
    }

    bool GetRespones(std::shared_ptr<Socket> &socket, Response &res, std::string buffer)
    {
        // std::string buffer;(这个字符串一定要从外面传入,因为读取是加等,如果一次堆积了多个报文未处理,这里的功能只会处理一个)
        while (true)
        {
            int n = socket->Recv(&buffer);
            if (n > 0)
            {

                // std::cout << buffer << std::endl;
                std::string pack;
                // if(!Decode(buffer, &pack))
                // {
                //     continue;
                // }
                // std::cout << "---------client_recv_string_buffer------" << std::endl;
                // std::cout << buffer << std::endl;
                // std::cout << "----------------------------------------" << std::endl;
                while (Decode(buffer, &pack))
                {
                    // std::cout << "---------client_recv_string_pack--------" << std::endl;
                    // std::cout << pack << std::endl;
                    // std::cout << "----------------------------------------" << std::endl;

                    // std::cout << "---------client_recv_string_buffer------" << std::endl;
                    // std::cout << buffer << std::endl;
                    // std::cout << "----------------------------------------" << std::endl;
                    res.Deserialize(pack);
                    res.LestRelust();
                }
                // std::cout << pack << std::endl;
                // res.Deserialize(pack);
                return true;
            }
            else if (n == 0)
            {
                std::cerr << "server quit" << std::endl;
                return false;
            }
            else
            {
                std::cerr << "recv error" << std::endl;
                return false;
            }
        }
        return true;
    }

    std::string BuildRequestSring(Request &req)
    {
        // 将输入信息序列化
        std::string send = req.Serialize();
        // 为输入信息添加报文
        send = Encode(send);
        return send;
    }
    ~Protocol() {}

private:
    func_t _func;
};